// TechObjectEditor.xaml.cs
//
// Copyright (c) 2007 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;

using Avalon.Windows.Utility;

using Supremacy.Tech;
using Supremacy.Text;

using Microsoft.Win32;
using System.IO;
using Avalon.Windows.Controls;
using Supremacy.Data;

namespace Supremacy.Editor
{
    /// <summary>
    /// Interaction logic for TechObjectEditor.xaml
    /// </summary>

    public partial class TechObjectEditor
    {
        #region Static Members
        public static readonly RoutedUICommand AddPrerequisiteGroupCommand;
        public static readonly RoutedUICommand AddPrerequisiteCommand;
        public static readonly RoutedUICommand DeletePrerequisiteCommand;
        public static readonly RoutedUICommand AddObsoletedItemCommand;
        public static readonly RoutedUICommand DeleteObsoletedItemCommand;
        public static readonly RoutedUICommand AddUpgradeOptionCommand;
        public static readonly RoutedUICommand DeleteUpgradeOptionCommand;

        static TechObjectEditor()
        {
            AddPrerequisiteGroupCommand = new RoutedUICommand(
                "New Prerequisite Group",
                "AddPrerequisiteGroup",
                typeof(TechObjectEditor));

            AddPrerequisiteCommand = new RoutedUICommand(
                "New Prerequisite",
                "AddPrerequisite",
                typeof(TechObjectEditor));

            DeletePrerequisiteCommand = new RoutedUICommand(
                "Delete Prerequisite",
                "DeletePrerequisite",
                typeof(TechObjectEditor));

            AddObsoletedItemCommand = new RoutedUICommand(
                "New Obsoleted Item",
                "AddObsoletedItem",
                typeof(TechObjectEditor));

            DeleteObsoletedItemCommand = new RoutedUICommand(
                "Delete Obsoleted Item",
                "DeleteObsoletedItem",
                typeof(TechObjectEditor));

            AddUpgradeOptionCommand = new RoutedUICommand(
                "New Upgrade Option",
                "AddUpgradeOption",
                typeof(TechObjectEditor));

            DeleteUpgradeOptionCommand = new RoutedUICommand(
                "Delete Upgrade Option",
                "DeleteUpgradeOption",
                typeof(TechObjectEditor));
        }
        #endregion

        private ObjectString _objectString;
        private ObjectStringLocalizedTextEntry _nameEntry;
        private ObjectStringLocalizedTextEntry _descriptionEntry;
        private readonly DataTemplate _itemTemplate;

        public ObjectString ObjectString
        {
            get { return _objectString; }
            protected set
            {
                _objectString = value;
                OnPropertyChanged("ObjectString");
            }
        }

        public ObjectStringLocalizedTextEntry NameEntry
        {
            get { return _nameEntry; }
        }

        public ObjectStringLocalizedTextEntry DescriptionEntry
        {
            get { return _descriptionEntry; }
        }

        public TechObjectEditor()
        {
            InitializeComponent();

            _itemTemplate = FindResource("TechObjectNameTemplate") as DataTemplate;

            DataContextChanged += TechObjectEditor_DataContextChanged;
            IdentityText.TextChanged += IdentityText_TextChanged;
        }

        void AddPrerequisiteGroup(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design == null)
                return;

            IList<TechObjectDesign> group = new List<TechObjectDesign>();
            design.Prerequisites.Add(group);

            PrerequisitesTree.Items.Refresh();
        }

        void AddPrerequisite(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design == null)
                return;

            var group = PrerequisitesTree.SelectedItem as IList<TechObjectDesign>;
            if (group == null)
            {
                var selectedItem = PrerequisitesTree.SelectedItem;
                if (selectedItem != null)
                {
                    var treeViewItem = UIHelpers.FindVisualDescendants(
                        PrerequisitesTree,
                        o => o is TreeViewItem && ((TreeViewItem)o).IsSelected).FirstOrDefault() as TreeViewItem;
                    if (treeViewItem != null)
                    {
                        treeViewItem = UIHelpers.FindVisualAncestorByType<TreeViewItem>(
                            VisualTreeHelper.GetParent(treeViewItem));
                        if (treeViewItem != null)
                            group = treeViewItem.DataContext as IList<TechObjectDesign>;
                    }
                }
            }
            if ((group == null) || !design.Prerequisites.Contains(group))
            {
                group = new List<TechObjectDesign>();
                design.Prerequisites.Add(group);
            }

            var omissions = new List<TechObjectDesign>
                            {
                                design
                            };

            omissions.AddRange(group);

            var selections = TechObjectSelectorWindow.GetSelections(omissions);
            if (selections == null)
                return;

            foreach (var selection in selections)
                group.Add(selection);

            PrerequisitesTree.Items.Refresh();
            foreach (var prereqGroup in design.Prerequisites)
            {
                CollectionViewSource.GetDefaultView(prereqGroup).Refresh();
            }
        }

        void DeletePrerequisite(object sender, RoutedEventArgs e)
        {
            if (PrerequisitesTree.SelectedItem == null)
                return;

            var design = this.DataContext as TechObjectDesign;
            if (design == null)
                return;

            var group = PrerequisitesTree.SelectedItem as IList<TechObjectDesign>;
            if (group != null)
            {
                design.Prerequisites.Remove(group);
                PrerequisitesTree.Items.Refresh();
                return;
            }

            var selectedItem = PrerequisitesTree.SelectedItem as TechObjectDesign;
            if (selectedItem == null)
                return;

            var treeViewItem = UIHelpers.FindVisualDescendants(
                        PrerequisitesTree,
                        o => o is TreeViewItem && ((TreeViewItem)o).IsSelected).FirstOrDefault() as TreeViewItem;
            if (treeViewItem == null)
                return;
            

            treeViewItem = UIHelpers.FindVisualAncestorByType<TreeViewItem>(
                VisualTreeHelper.GetParent(treeViewItem));
            if (treeViewItem != null)
                group = treeViewItem.DataContext as IList<TechObjectDesign>;

            if (group == null)
                return;

            group.Remove(selectedItem);
            if (group.Any())
            {
                CollectionViewSource.GetDefaultView(group).Refresh();
                return;
            }

            design.Prerequisites.Remove(group);
            PrerequisitesTree.Items.Refresh();
        }

        void AddObsoletedItem(object sender, RoutedEventArgs e)
        {
            var design = this.DataContext as TechObjectDesign;

            if (design == null)
                return;

            var omissions = new List<TechObjectDesign>
                            {
                                design
                            };

            foreach (TechObjectDesign obsoletedItem in design.ObsoletedDesigns)
                omissions.Add(obsoletedItem);

            var selections = TechObjectSelectorWindow.GetSelections(omissions);

            if (selections == null)
                return;

            foreach (var selection in selections)
                design.ObsoletedDesigns.Add(selection);

            ObsoletedItemList.Items.Refresh();
        }

        void DeleteObsoletedItem(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design == null)
                return;

            TechObjectDesign selection = ObsoletedItemList.SelectedItem as TechObjectDesign;
            if (selection == null)
                return;

            design.ObsoletedDesigns.Remove(selection);
            ObsoletedItemList.Items.Refresh();
        }

        void AddUpgradeOption(object sender, RoutedEventArgs e)
        {
            var design = this.DataContext as TechObjectDesign;

            if (design == null)
                return;

            var omissions = new List<TechObjectDesign>
                            {
                                design
                            };

            foreach (TechObjectDesign upgradeOption in design.UpgradableDesigns)
                omissions.Add(upgradeOption);

            var selections = TechObjectSelectorWindow.GetSelections(omissions);

            if (selections == null)
                return;
            
            foreach (var selection in selections)
                design.UpgradableDesigns.Add(selection);
            
            UpgradeList.Items.Refresh();
        }

        void DeleteUpgradeOption(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design == null)
                return;

            TechObjectDesign selection = UpgradeList.SelectedItem as TechObjectDesign;
            if (selection == null)
                return;

            design.UpgradableDesigns.Remove(selection);
            UpgradeList.Items.Refresh();
        }

        void TechObjectEditor_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            TechObjectDesign design = e.NewValue as TechObjectDesign;

            if (design == null)
            {
                return;
            }

            this.ObjectString = design.ObjectString;

            UpdateLocalizedTextEntries();
            
            OnPropertyChanged("NameEntry");
            OnPropertyChanged("DescriptionEntry");

            //PopulatePrerequisiteTree();
            PrerequisitesTree.ItemsSource = design.Prerequisites;
            ObsoletedItemList.ItemsSource = design.ObsoletedDesigns;
            UpgradeList.ItemsSource = design.UpgradableDesigns;
        }

        private TreeViewItem FindSelectionHeader(TechObjectDesign design)
        {
            if (design == null)
                return null;

            foreach (TreeViewItem item in PrerequisitesTree.Items)
            {
                foreach (TechObjectDesign prereq in item.Items)
                {
                    if (prereq == design)
                    {
                        TreeViewItem container =
                            item.ItemContainerGenerator.ContainerFromItem(design) as TreeViewItem;
                        if ((container != null)
                            && container.IsSelected)
                        {
                            return item;
                        }
                    }
                }
            }

            return null;
        }

        private void PopulatePrerequisiteTree()
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;

            if (design == null)
                return;

            PrerequisitesTree.Items.Clear();

            int i = 1;
            foreach (IList<TechObjectDesign> group in design.Prerequisites)
            {
                TreeViewItem item = new TreeViewItem
                                    {
                                        Header = String.Format("Group {0}", i++),
                                        ItemsSource = group,
                                        ItemTemplate = _itemTemplate,
                                        IsExpanded = true
                                    };
                PrerequisitesTree.Items.Add(item);
            }
        }

        void IdentityText_TextChanged(object sender, TextChangedEventArgs e)
        {
            UpdateIdentity();
        }

        private void UpdateIdentity()
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design != null)
            {
                design.Key = IdentityText.Text;
                //if (_nameEntry != null)
                //{
                //    _nameEntry.Key = "TECH_NAME_" + design.Key;
                //    design.Name = _nameEntry.Key;
                //    OnPropertyChanged("NameEntry");
                //}
                //if (_isDescriptionUnique && (_descriptionEntry != null))
                //{
                //    _descriptionEntry.Key = "TECH_DESC_" + design.Key;
                //    design.Description = _descriptionEntry.Key;
                //    OnPropertyChanged("DescriptionEntry");
                //}
            }
        }

        private void ResetImageButton_Click(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design != null)
            {
                design.Image = null;
            }
        }

        private void SelectImageButton_Click(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design != null)
            {
                string imageDirectory = Path.Combine(EditorContext.WorkingDirectory, "Resources\\Images\\TechObjects\\");
                OpenFileDialog dialog = new OpenFileDialog
                                        {
                                            Filter = "Image Files (*.png, *.jpg)|*.png;*.jpg",
                                            AddExtension = true,
                                            CheckPathExists = true,
                                            CheckFileExists = true,
                                            Multiselect = false,
                                            InitialDirectory = imageDirectory,
                                            ValidateNames = true,
                                            RestoreDirectory = true
                                        };

                bool? result = dialog.ShowDialog();
                if (result.Value)
                {
                    string imagePath = dialog.FileName;
                    try
                    {
                        string fileName = Path.GetFileName(imagePath);
                        string desiredFileName = design.Key.ToLowerInvariant() + Path.GetExtension(fileName);

                        if (Supremacy.Resources.ResourceManager.GetSystemResourcePath(imagePath).Equals(
                            Supremacy.Resources.ResourceManager.GetSystemResourcePath(design.Image),
                            StringComparison.OrdinalIgnoreCase))
                        {
                            return;
                        }

                        if (Path.GetDirectoryName(imagePath) != Path.GetDirectoryName(imageDirectory))
                        {
                            if (File.Exists(Path.Combine(imageDirectory, desiredFileName)))
                            {
                                TaskDialog taskDialog = new TaskDialog
                                                        {
                                                            IsExpanded = false,
                                                            Title = "Supremacy Editor",
                                                            Header = "File Name Conflict",
                                                            Content =
                                                                ("Another image already exists with the desired file name for this object."
                                                                 + Environment.NewLine
                                                                 + "How would you like to proceed?")
                                                        };
                                taskDialog.CommandLinks.Add(
                                    new TaskDialogButtonData(
                                        TaskDialogButtons.Yes,
                                        "Overwrite", "Use the same file name and replace the existing file.",
                                        false));
                                taskDialog.CommandLinks.Add(
                                    new TaskDialogButtonData(
                                        TaskDialogButtons.No,
                                        "Leave It", "Use an alternate file name and leave the existing file intact.",
                                        false));
                                taskDialog.MainIcon = TaskDialogIconConverter.ConvertFrom(
                                    TaskDialogIcon.Question);
                                taskDialog.MaxWidth = 640;
                                taskDialog.Owner = EditorApp.Current.MainWindow;
                                taskDialog.Show();
                                if (taskDialog.Result.StandardButton == TaskDialogButtons.Yes)
                                    fileName = desiredFileName;
                            }
                            else
                            {
                                fileName = desiredFileName;
                            }

                            string destFileName = Path.Combine(imageDirectory, fileName);
                            File.Copy(imagePath, destFileName, true);
                        }

                        design.Image = (fileName == desiredFileName) ? null : fileName.ToLowerInvariant();
                    }
                    catch (Exception ex)
                    {
                        TaskDialog taskDialog = new TaskDialog
                                                {
                                                    IsExpanded = false,
                                                    ExpansionButtonContent = "Details",
                                                    ExpansionContent = ex.Message,
                                                    ExpansionPosition = TaskDialogExpansionPosition.Header,
                                                    Title = "Supremacy Editor",
                                                    Header = "Could not copy file.",
                                                    Content =
                                                        "The Supremacy Editor could not copy the selected image file to the resource directory."
                                                };
                        taskDialog.Buttons.Add(TaskDialogButtons.OK);
                        taskDialog.MainIcon = TaskDialogIconConverter.ConvertFrom(TaskDialogIcon.Error);
                        taskDialog.MaxWidth = 640;
                        taskDialog.Owner = EditorApp.Current.MainWindow;
                        taskDialog.Show();
                    }
                }
            }
        }

        private void LinkImageButton_Click(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design != null)
            {
                var omissions = from o in EditorContext.TechDatabase
                                where (o == design) || !design.GetType().IsAssignableFrom(o.GetType())
                                select o;
                TechObjectDesign linkTarget = TechObjectSelectorWindow.GetSelection(omissions);
                if (linkTarget != null)
                {
                    design.LinkImageToDesign(linkTarget);
                }
            }
        }

        private void LocalizeNamesButton_Click(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design != null)
            {
                ObjectStringLocalizedTextGroup group = new ObjectStringLocalizedTextGroup(design.Key, "Name");
                group.ListChanged += Group_ListChanged;
                new LocalizedTextEditor(group).ShowDialog();
                group.ListChanged -= Group_ListChanged;
            }
        }

        private void LocalizeDescriptionButton_Click(object sender, RoutedEventArgs e)
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if (design != null)
            {
                ObjectStringLocalizedTextGroup group = new ObjectStringLocalizedTextGroup(design.Key, "Description");
                group.ListChanged += Group_ListChanged;
                new LocalizedTextEditor(group).ShowDialog();
                group.ListChanged -= Group_ListChanged;
            }
        }


        private void Group_ListChanged(object sender, ListChangedEventArgs e)
        {
            if (e.ListChangedType == ListChangedType.ItemDeleted)
            {
                UpdateLocalizedTextEntries();
            }
        }

        private void UpdateLocalizedTextEntries()
        {
            TechObjectDesign design = this.DataContext as TechObjectDesign;
            if ((design != null) && !String.IsNullOrEmpty(design.Key))
            {
                if (_nameEntry != null)
                {
                    _nameEntry.Dispose();
                    _nameEntry = null;
                }

                if (_descriptionEntry != null)
                {
                    _descriptionEntry.Dispose();
                    _descriptionEntry = null;
                }

                if (_objectString != null)
                {
                    _nameEntry = new ObjectStringLocalizedTextEntry(design.ObjectString, "Name");
                    _descriptionEntry = new ObjectStringLocalizedTextEntry(design.ObjectString, "Description");
                }

                OnPropertyChanged("NameEntry");
                OnPropertyChanged("DescriptionEntry");
            }
        }
    }
}